package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.FPSAnimator;

import db.DBConnection;

public class Graph implements GLEventListener {

	private GLCanvas canvas;
	private Animator animator;
	private JPanel panel;

	// For specifying the positions of the clipping planes (increase/decrease
	// the distance) modify this variable.
	// It is used by the glOrtho method.
	private double v_size = 1.0;
	private BufferedImage scale;
	private Vector<Double> v;

	// Application main entry point

	// Default constructor
	public Graph(String table) {
		panel = new JPanel();
		panel.setLayout(new BorderLayout());
		panel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
		panel.setSize(600, 450);
		panel.setLocation(80, 40);
		init(table);
		this.initializeJogl();
	}

	public JPanel getPanel() {
		return panel;
	}

	private void initializeJogl() {
		// Creating an object to manipulate OpenGL parameters.
		GLCapabilities capabilities = new GLCapabilities();

		// Setting some OpenGL parameters.
		capabilities.setHardwareAccelerated(true);
		capabilities.setDoubleBuffered(true);

		// Try to enable 2x anti aliasing. It should be supported on most
		// hardware.
		capabilities.setNumSamples(2);
		capabilities.setSampleBuffers(true);

		// Creating an OpenGL display widget -- canvas.
		this.canvas = new GLCanvas(capabilities);

		// Adding the canvas in the center of the frame.
		panel.add(this.canvas, BorderLayout.CENTER);

		// Adding an OpenGL event listener to the canvas.
		this.canvas.addGLEventListener(this);

		// Creating an animator that will redraw the scene 40 times per second.
		this.animator = new FPSAnimator(40);

		// Registering the canvas to the animator.
		this.animator.add(this.canvas);

		// Starting the animator.
		this.animator.start();
	}

	public void init(GLAutoDrawable canvas) {
		// Obtaining the GL instance associated with the canvas.
		GL gl = canvas.getGL();

		// Setting the clear color -- the color which will be used to erase the
		// canvas.
		gl.glClearColor(0, 0, 0, 0);

		// Selecting the modelview matrix.
		gl.glMatrixMode(GL.GL_MODELVIEW);

	}

	public void painGrid(GL gl) {
		double gray = 220.0 / 255.0;
		double step = 2.4 / 12.3;
		gl.glBegin(GL.GL_LINES);
		gl.glColor3d(gray, gray, gray);
		for (double i = -1; i <= 1.4; i += step) {
			gl.glVertex2d(i, 0);
			gl.glVertex2d(i, 1.5);
		}
		for (double i = 0; i <= 1.5; i += 0.25) {
			gl.glVertex2d(-1, i);
			gl.glVertex2d(1.4, i);
		}
		gl.glEnd();
	}

	public void display(GLAutoDrawable canvas) {
		GL gl = canvas.getGL();

		// Erasing the canvas -- filling it with the clear color.
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

		gl.glLineWidth(2);
		painGrid(gl);
		gl.glLineWidth(2);
		gl.glBegin(GL.GL_LINES);
		double x = -1;
		double xI = 2.4 / v.size();
		for (int i = 0; i < v.size() - 1; i++) {
			Double d1 = v.get(i);
			Double d2 = v.get(i + 1);
			setColor(d1, gl);
			gl.glVertex2d(x, d1);
			x += xI;
			setColor(d2, gl);
			gl.glVertex2d(x, d2);

		}

		gl.glEnd();
		gl.glFlush();
	}

	private void setColor(Double d, GL gl) {
		Double dRGB = Math.min(d * 300, 299);
		int rgb = scale.getRGB(2, (int) ((double) dRGB));
		int red = (rgb & 0x00ff0000) >> 16;
		int green = (rgb & 0x0000ff00) >> 8;
		int blue = rgb & 0x000000ff;
		gl.glColor3d(red / 255.0, green / 255.0, blue / 255.0);
	}

	public void init(String table) {
		try {
			scale = ImageIO.read(new File("lib/GraphScale.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		DBConnection.initMap();
		DBConnection.build(DBConnection.select(table, "Electric", false));
		DBConnection.build(DBConnection.select(table, "Gas", true));
		v = new Vector<Double>();
		Set<Integer> st = DBConnection.getData().keySet();
		SortedSet<Integer> stt = new TreeSet<Integer>(st);
		Iterator<Integer> it = stt.iterator();
		int counter = 0;
		total = 0;
		max = 0;
		avg = 0;
		while (it.hasNext()) {
			counter++;
			Integer n = it.next();
			Double d = DBConnection.getData().get(n);
			total += d;
			if (d > max)
				max = d;
			System.out.println(n + " " + d);
			d = d / 3000.0;
			v.add(d);
		}
		avg = total / (double) counter;
		avg /= 1000.0;
		total = total / (double) counter / 1000.0 * 24.0;
		max /= 1000.0;
		System.out.println("avg = " + avg + " total = " + total + " max = "
				+ max);

		System.out.println("element count = " + counter);

	}

	public double getMax() {
		return max;
	}

	public double getTotal() {
		return total;
	}

	public double getAvg() {
		return avg;
	}

	private double total = 0, max = 0, avg = 0;

	public void reshape(GLAutoDrawable canvas, int left, int top, int width,
			int height) {
		GL gl = canvas.getGL();

		// Selecting the viewport -- the display area -- to be the entire
		// widget.
		gl.glViewport(0, 0, width, height);

		// Determining the width to height ratio of the widget.
		double ratio = (double) width / (double) height;

		// Selecting the projection matrix.
		gl.glMatrixMode(GL.GL_PROJECTION);

		gl.glLoadIdentity();

		if (ratio < 1)
			gl.glOrtho(-v_size, v_size, 0, 1.5 / ratio, -1, 1);
		else
			gl.glOrtho(-v_size, v_size * ratio, 0, 1.5, -1, 1);

		// Selecting the modelview matrix.
		gl.glMatrixMode(GL.GL_MODELVIEW);
	}

	public void displayChanged(GLAutoDrawable canvas, boolean modeChanged,
			boolean deviceChanged) {
		return;
	}

	public static void main(String args[]) {
		Graph gtest = new Graph("ll");
		JFrame frame = new JFrame();
		JPanel panel = new JPanel();
		panel.setLayout(null);
		panel.setSize(800, 600);
		panel.add(gtest.panel);
		frame.setSize(800, 600);
		frame.add(panel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
